var version = "0.03";
var logWindow = null;
var worldMap = null;
var worldMapMode = null;
var titleMode = null;
var modeStack = [];
var player = null;
var frame = 0;
var inGameMode = false;

function main()
{
	host.init(60, 36, onInputAction);
	enterTitleMode();
}
function onInputAction(action)
{
	// Let the log window get the first crack at it.
	if(logWindow &&
		logWindow.handleAction(action))
		return;
	for(var i = modeStack.length - 1; i >= 0; --i)
	{
		if(!modeStack[i].handleAction)
			continue;
		if(modeStack[i].handleAction(action))
			break;
	}
}
function removeMode(mode)
{
	var idx = modeStack.indexOf(mode);
	if(idx >= 0)
		modeStack.splice(idx, 1);
	for(var i = 0; i < modeStack.length; ++i)
	{
		if(modeStack[i].render)
			modeStack[i].render();
	}
	if(logWindow)
		logWindow.render();
}
function enterTitleMode()
{
	leaveGameMode();
	leaveTitleMode();
	titleMode = new TitleScreenMode();
	modeStack.push(titleMode);
	titleMode.createMainMenu();
}
function leaveTitleMode()
{
	removeMode(titleMode);
}
function enterGameMode()
{
	leaveTitleMode();
	leaveGameMode();
	logWindow = new LogWindow(host.screen, 0, 32, 60, 4, 128);
	worldMapMode = new WorldMapMode(worldMap);
	modeStack.push(worldMapMode);
}
function leaveGameMode()
{
	logWindow = null;
	removeMode(worldMapMode);
}
function saveGame()
{
	// See if saving works
	if(!host.isSaveAvailable())
	{
		logWindow.pushMessage("%90Saving is not supported.");
		return false;
	}

	var saveData;

	try
	{
		// Build the save data
		var worldMapData = [];
		worldMap.serialize(worldMapData);
		var save =
		{
			version: version,
			seed: worldMap.seed,
			player: Entity.getSerializedForm(player),
			worldMap: worldMapData,
			sectorMaps: SectorMap.getSaveData()
		}
		saveData = JSON.stringify(save);
		host.saveData("save", saveData);
	}
	catch(exp)
	{
		reportCriticalError("Saving game failed: " + exp.toString());
		return false;
	}

	logWindow.pushMessage("%a0Saved game " + save.seed + " successfully (" + util.bytesToKb(saveData.length) + "kb).");
	return true;
}
function isSaveAvailable()
{
	// See if saving works
	if(!host.isSaveAvailable())
		return false;
	return host.isValueAvailable("save");
}
function loadGame()
{
	// See if saving works
	if(!host.isSaveAvailable())
	{
		reportCriticalError("Saving is not supported.");
		return false;
	}

	var saveData = null;

	try
	{
		saveData = host.loadData("save");
		if(!saveData)
			return false;
		var save = JSON.parse(saveData);
		if(save.version !== version)
		{
			reportCriticalError("The saved game present is for version " + save.version + " and is not compatible.");
			return false;
		}

		// Load proceedure
		player = Entity.fromSerializedData(save.player);
		SectorMap.unregisterAllMaps();
		worldMap = new WorldMap(host.screen, 0, 0, 40, 32, save.seed, player);
		worldMap.deserialize(save.worldMap);
		SectorMap.loadSaveData(save.sectorMaps);
	}
	catch(exp)
	{
		reportCriticalError("Loading game failed: " + exp.toString());
		return false;
	}

	leaveTitleMode();
	enterGameMode();
	logWindow.pushMessage("%a0Game " + save.seed + " loaded successfully (" + util.bytesToKb(saveData.length) + "kb).");
	return true;
}
function newGame()
{
	deleteSave();
	player = new PlayerMobile("Playa", "@", Color.white, Color.black, 20);
	SectorMap.unregisterAllMaps();
	var seed = Math.floor(Math.random() * 10000);
	//seed = 6811;
	worldMap = new WorldMap(host.screen, 0, 0, 40, 32, seed, player);
	leaveTitleMode();
	enterGameMode();
	logWindow.pushMessage("%a0Started new game " + seed + ".");
	textBox("General Help");
}
function deleteSave()
{
	try
	{
		host.deleteData("save");
	}
	catch(exp)
	{
	}
}
/** Utility method for displaying a message box.
 *@param text The text to display. Do not include newlines.
 */
function messageBox(text)
{
	modeStack.push(
		new MenuListMode(
			host.screen,
			40,
			text,
			null,
			null
		)
	);
}
/** Standard critical error reporting method.
 *@param error A description of the error.
 */
function reportCriticalError(error)
{
	messageBox("%90" + error);
}
/** Quickly pull up a standard text box.
 *@param name Name of the text resource to display in the text box.
 */
function textBox(name)
{
	modeStack.push(
		new TextReaderMode(
			host.screen,
			"%f0" + text[name],
			null,
			null
		)
	);
}
